修飾子,在程式語言中指的是用來修飾「屬性」或「方法」的關鍵字。
又分為:
靜態修飾子 static 的特點是不須先建立物件就能直接使用,可以省下不必要的記憶體空間使用。適用於全域共用、不會因不同物件而有不同的屬性。
不過需要注意的是,static 屬性要謹慎使用。要避免把每個物件都應該不同的屬性設成 static,否則會出現個別資料被錯誤混用的問題。另外,若程式中大量依賴 static 屬性,會讓資料在多處共享,導致狀態可能被污染、難以追蹤與測試,降低程式的可維護性與彈性。
靜態修飾子和存取修飾子的使用時機以下直接舉例說明會比較好理解:
假設我們要開發一個公司的內部員工系統,會有「公司 (Company)」與「員工 (Employee)」等類別。
這些類別會包含不同屬性,例如:
公司名稱、公司規定的最低薪資
員工姓名、職稱、薪資等
其中,公司名稱與最低薪資標準屬於整個公司共用、不會因個別員工而改變的資料,
因此適合設為 static 屬性。
至於員工姓名、職稱、薪資等屬性則屬於每個員工個別擁有的資料,而這些屬性的「可見度」就要依照業務邏輯決定。
例如,假設要讓系統各處都能顯示員工姓名,並且員工姓名沒有相關的業務邏輯需要被保護,則可以將它設為 public。
而如果員工薪資只有在需要顯示、計算薪資的模組才會用到,則可設為 private 或 protected。例如:員工的基本薪資屬性,如果未來有「固定薪資員工」與「時薪員工」子類別要使用,可以設 protected,方便子類別計算薪資。
const 和 readonly 最大的差別在於:const 是 static 屬性,他不屬於任何物件,無法在 runtime 改變;而 readonly 則屬於實例屬性,能夠在建構子中設定一次,設定之後就不能再修改。
建構子(__construct())是當物件「出生」時自動執行的初始化動作。
常見用途:
* 設定初始屬性值
* 檢查參數是否合法
* 進行依賴注入
* 建立資料庫連線或開啟檔案等初始化動作
解構子(__destruct()) 則是當物件不再被使用(例如程式結束或變數被釋放)時,系統會自動呼叫的方法。
常見用途:
<?php
class Company
{
// 公司名稱不會因不同員工而有不同,因此設為 static 屬性
public static string $name = 'TechNova Inc.';
/*
公司統一規定的最低薪資標準(全員共用,不隨個別員工變動)
因此設為 static 屬性以便整個系統共用與存取
*/
public static int $minimumSalary = 30000;
}
class Employee
{
public string $name;
public string $position;
// 私有屬性,避免外部直接改動
private int $salary;
// 建構子
public function __construct(string $name, string $position, int $salary)
{
$this->name = $name;
$this->position = $position;
$this->setSalary($salary);
}
// 解構子:物件銷毀時自動執行
public function __destruct()
{
echo "員工 {$this->name} 離開系統。\n";
}
// 使用 private 封裝邏輯
private function setSalary(int $salary)
{
// 若薪資低於公司規定的最低薪資,則自動調整
$this->salary = max($salary, Company::$minimumSalary);
}
// Public 方法讓外部查詢薪水
public function getSalary(): int
{
return $this->salary;
}
// 靜態方法:顯示公司資訊(可不依賴員工物件)
public static function companyInfo(): void
{
echo "Company: " . Company::$name . PHP_EOL;
echo "Minimum Salary: " . Company::$minimumSalary . PHP_EOL;
}
}
// === 測試 ===
Employee::companyInfo();
$john = new Employee('John', 'Backend Engineer', 28000);
$jane = new Employee('Jane', 'Team Lead', 55000);
echo $john->name . ' salary: ' . $john->getSalary() . PHP_EOL;
echo $jane->name . ' salary: ' . $jane->getSalary() . PHP_EOL;
unset($emp); // 手動銷毀物件,呼叫解構子